#include "gwbase/byte_array.h"

#include <sstream>
#include <assert.h>

#include <gwbase/base/util.h>
#include "gwbase/base64.h"
#include "gwbase/encrypt/enc_rand.h"

namespace dicom {

std::string ByteArray::toRawStr() const
{
	return std::string(this->begin(), this->end());
}

std::string ByteArray::toHexStr() const
{
	std::string out;
	out.reserve(this->size() * 2 + 1);  
	for (size_t i = 0; i < this->size(); ++i)
		out += StringPrintf("%02x", static_cast<int>(this->at(i)));

	return out;
}

ByteArray ByteArray::fromRawStr(const std::string &raw)
{
	ByteArray out;
	const uint8_t *start = reinterpret_cast<const uint8_t *>(raw.c_str());
	out.insert(out.end(), start, start + raw.length());
	return out;
}

static uint8_t HexToInt(uint8_t ch)
{
	if (ch >= 'a' && ch <= 'z')
		return static_cast<uint8_t>(ch - 'a' + 10);

	if (ch >= '0' && ch <= '9')
		return static_cast<uint8_t>(ch - '0');

	if (ch >= 'A' && ch <= 'Z')
		return static_cast<uint8_t>(ch - 'A' + 10);

	assert (false);
	return 0;
}

ByteArray ByteArray::fromHexStr(const std::string &hex)
{
	assert (hex.size() % 2 == 0);
	ByteArray out;
	for (unsigned i = 0; i < hex.length(); i+=2)
	{
		uint8_t high = HexToInt(hex[i]);
		uint8_t low = HexToInt(hex[i+1]);
		out.push_back(static_cast<uint8_t>((high << 4) | low));
	}
	return out;
}

std::string ByteArray::toBase64Str() const
{
	return Base64Helper::Encode(*this);
}

std::string ByteArray::toUrlBase64Str() const
{
	return UrlBase64Helper::Encode(*this);
}

ByteArray ByteArray::genRandom(size_t size)
{
	ByteArray bytes(size);
  EncGenRandom(&bytes[0], bytes.size());
	return bytes;
}

}
